# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
# Contributor: Sheila Aman <sheila@vulpine.house>
pkgname=python3
# the python3-tkinter's pkgver needs to be synchronized with this.
pkgver=3.12.3
_basever="${pkgver%.*}"
pkgrel=1
pkgdesc="High-level scripting language"
url="https://www.python.org/"
arch="all"
license="PSF-2.0"
# pyc0 comes last because the files are named without a unique substring
subpackages="
	$pkgname-dbg
	$pkgname-dev
	$pkgname-doc
	$pkgname-tests::noarch
	$pkgname-pyc:_default_pyc
	$pkgname-pycache-pyc2
	$pkgname-pycache-pyc1
	$pkgname-pycache-pyc0
	$pkgname-gdbm
	pyc:_pyc_meta:noarch
	"
depends="libssl3>=3.3.0"
makedepends="
	!gettext-dev
	bluez-headers
	bzip2-dev
	expat-dev
	gdbm-dev
	libffi-dev
	linux-headers
	mpdecimal-dev
	musl-libintl
	ncurses-dev
	openssl-dev
	readline-dev
	sqlite-dev
	tcl-dev
	xz-dev
	zlib-dev
	"
source="https://www.python.org/ftp/python/$pkgver/Python-$pkgver.tar.xz
	externally-managed
	musl-find_library.patch
	"
options="net" # Required for tests
builddir="$srcdir/Python-$pkgver"

# secfixes:
#   3.11.5-r0:
#     - CVE-2023-40217
#   3.11.1-r0:
#     - CVE-2022-45061
#   3.10.5-r0:
#     - CVE-2015-20107
#   3.9.5-r0:
#     - CVE-2021-29921
#   3.9.4-r0:
#     - CVE-2021-3426
#   3.8.8-r0:
#     - CVE-2021-23336
#   3.8.7-r2:
#     - CVE-2021-3177
#   3.8.5-r0:
#     - CVE-2019-20907
#   3.8.4-r0:
#     - CVE-2020-14422
#   3.8.2-r0:
#     - CVE-2020-8315
#     - CVE-2020-8492
#   3.7.5-r0:
#     - CVE-2019-16056
#     - CVE-2019-16935
#   3.6.8-r1:
#     - CVE-2019-5010

# was briefly present, and is in 3.16
provides="pythonispython3=$pkgver-r$pkgrel"

prepare() {
	default_prepare

	# force system libs
	rm -r Modules/expat
}

build() {
	# set thread stack size to 2MB so we don't segfault before we hit
	# sys.getrecursionlimit()
	# note: raised from 1 as we ran into some stack limit on x86_64 too
	# sometimes, but not recursion
	local stacksize=0x200000

	# we want -O2 here for more speed for such a large interpreter.
	export CFLAGS_NODIST="$CFLAGS -O2 -DTHREAD_STACK_SIZE=$stacksize"
	export CXXFLAGS_NODIST="$CXXFLAGS -O2"
	export LDFLAGS_NODIST="$LDFLAGS"

	case "$CARCH" in
	ppc64le)
		# FIXME: on ppc64le, the stack-clash-protection from gcc seems to segfault
		# python.. sometimes. not sure if python or gcc bug (probably former)
		# for an easy reproduction, run the testsuite of community/py3-lmdb
		export CFLAGS_NODIST="${CFLAGS_NODIST/-fstack-clash-protection}"
		export CXXFLAGS_NODIST="${CXXFLAGS_NODIST/-fstack-clash-protection}"
		;;
	esac

	# we set them via NODIST to not propagate them and duplicate them to modules
	unset LDFLAGS CFLAGS CXXFLAGS CPPFLAGS

	./configure \
		--build=$CBUILD \
		--host=$CHOST \
		--prefix=/usr \
		--enable-ipv6 \
		--enable-loadable-sqlite-extensions \
		--enable-optimizations \
		--enable-shared \
		--with-lto \
		--with-computed-gotos \
		--with-dbmliborder=gdbm:ndbm \
		--with-system-expat \
		--with-system-libmpdec \
		--without-ensurepip

	make
}

check() {
	# test that we reach recursionlimit before we segfault
	cat > test-stacksize.py <<-EOF
	import threading
	import sys

	def fun(i):
	  try:
	    fun(i+1)
	  except:
	    sys.exit(0)

	t = threading.Thread(target=fun, args=[1])
	t.start()
EOF
	LD_LIBRARY_PATH=$PWD ./python test-stacksize.py

	local fail

	# musl related
	fail="test__locale"					# various musl locale deficiencies
	fail="$fail test_locale"
	fail="$fail test_re"
	fail="$fail test_c_locale_coercion"
	fail="$fail test_datetime"				# hangs if 'tzdata' installed
	fail="$fail test_os"					# fpathconf, ttyname errno values

	# FIXME: failures needing investigation
	fail="$fail test_ctypes"				# fail on aarch64 (ctypes.test.test_win32.Structures)

	# kernel related
	fail="$fail test_fcntl"					# wants DNOTIFY, we don't have it

	# test_clock_settime returns Function not implemented instead of the
	# expected permission error in docker (CI). Disable for now.
	case "$CARCH" in
		ppc64le) fail="$fail test_time";;
	esac

	make quicktest TESTOPTS="-j${JOBS:-$(nproc)} --exclude $fail"
}

package() {
	make -j1 DESTDIR="$pkgdir" EXTRA_CFLAGS="$CFLAGS" install maninstall
	install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE

	install -Dm644 "$srcdir"/externally-managed \
		"$pkgdir"/usr/lib/python$_basever/EXTERNALLY-MANAGED

	# those are provided by python3-tkinter
	rm -r "$pkgdir"/usr/bin/idle* "$pkgdir"/usr/lib/python*/idlelib \
		"$pkgdir"/usr/lib/python*/tkinter

	ln -s python3 "$pkgdir"/usr/bin/python
	ln -s python3-config "$pkgdir"/usr/bin/python-config
}

dev() {
	default_dev

	# pyconfig.h is needed runtime so we move it back
	mkdir -p "$pkgdir"/usr/include/python$_basever
	mv "$subpkgdir"/usr/include/python$_basever/pyconfig.h \
		"$pkgdir"/usr/include/python$_basever/
}

tests() {
	pkgdesc="The test modules from the main python package"

	amove usr/lib/python$_basever/test
}

gdbm() {
	pkgdesc="Python backend for GNU gdbm"

	amove usr/lib/python3*/lib-dynload/_gdbm.cpython*
}

_pyc_meta() {
	pkgdesc="Meta package for pulling in all -pyc packages"
	depends=""
	mkdir -p "$subpkgdir"
}

# python3-pyc, to install pyc by default
_default_pyc() {
	pkgdesc="$pkgdesc (install .pyc cache files)"
	install_if="$pkgname=$pkgver-r$pkgrel"
	depends="
		$pkgname-pycache-pyc0=$pkgver-r$pkgrel
		pyc
		"

	mkdir -p "$subpkgdir"
}

pyc0() {
	pkgdesc="$pkgdesc (.pyc pycache files)"

	cd "$pkgdir"
	amove $(find usr/lib/python3* -name "*.pyc")
}

pyc1() {
	pkgdesc="$pkgdesc (.opt-1.pyc pycache files)"

	cd "$pkgdir"
	amove $(find usr/lib/python3* -name "*.opt-1.pyc")
}

pyc2() {
	pkgdesc="$pkgdesc (.opt-2.pyc pycache files)"

	cd "$pkgdir"
	amove $(find usr/lib/python3* -name "*.opt-2.pyc")
}

sha512sums="
4a2213b108e7f1f1525baa8348e68b2a2336d925e60d0a59f0225fc470768a2c8031edafc0b8243f94dbae18afda335ee5adf2785328c2218fd64cbb439f13a4  Python-3.12.3.tar.xz
46dd8230ee2ab66e9c4157c10b2bd9c414fd7f30be0bee73e21a9eea88f63fff362d47828e0fc77ddc59df097b414b21505f8b5f98bc866381115c58ae3f4862  externally-managed
ab8eaa2858d5109049b1f9f553198d40e0ef8d78211ad6455f7b491af525bffb16738fed60fc84e960c4889568d25753b9e4a1494834fea48291b33f07000ec2  musl-find_library.patch
"
